/** Fichier implémentant un cylindre.
 *
 * Ce fichier contient l'implémentation de la classe Cylindre.
 *
 * @file Cylindre.cpp
 * @author Johan "Solo" Luisier
 * @date 2005
 */
#include "Cylindre.hpp"

#include "Plan.hpp"
#include "BaseCylindre.hpp"

#include "Utils/ATL.hpp"

using namespace std;

/** Constructeur par défaut.
 *
 * Ce constructeur initialise un cylindre de rayon et hauteur 1, dont
 * "l'origine" est en (0, 0, 0).
 */
Cylindre::Cylindre()
    : Centre( 0., 0., .5 ), Hauteur( 1. )
{
    Vecteur axe( 0., 0., 1. );
    Coord point( 0., 0., 0. );

    BCylindre = BaseCylindre::SharedPtr( new BaseCylindre( axe, point, 1. ) );

    ListPlan.push_back( Plan::SharedPtr( new Plan( -axe, point ) ) );
    ListPlan.push_back( Plan::SharedPtr( new Plan( axe, point + axe ) ) );

    form[ 0 ] = new FormeComposee( inter, BCylindre.get(), ListPlan[0].get() );
    form[ 1 ] = ListPlan[1].get();

    op = inter;

    PseudoCentre = Centre;

    PseudoRayon = sqrt( puissance< 2u >( 0.5 ) + puissance< 2u >( 0.5 ) );
}

/** Constructeur standard.
 *
 * Constructeur permettant la définition de tous les attributs d'un
 * Cylindre.
 *
 * @param[in] v axe du cylindre.
 * @param[in] a centre du cercle formant la base du Cylindre.
 * @param[in] r ryon du Cylindre.
 * @param[in] h hauteur du Cylindre.
 */
Cylindre::Cylindre(const Vecteur& v, const Coord& a, const double& r,
                   const double& h)
    : Centre( a + h * v * 0.5 ), Hauteur( h )
{
    BCylindre = BaseCylindre::SharedPtr( new BaseCylindre( v, a, abs( r ) ) );

    ListPlan.push_back( Plan::SharedPtr( new Plan( -v, a ) ) );
    ListPlan.push_back( Plan::SharedPtr( new Plan( v, a + v * h ) ) );

    cout << "Plan 'moins' : " << ListPlan[0]->point() << endl;
    cout << "Plan 'plus' : " << ListPlan[1]->point() << endl;

    form[ 0 ] = new FormeComposee( inter, BCylindre.get(), ListPlan[0].get() );
    form[ 1 ] = ListPlan[1].get();

    op = inter;

    PseudoCentre = Centre;

    PseudoRayon = 1.8 * sqrt( puissance< 2u >( h / 2. ) + puissance< 2u >( r ) );
}

/** Destructeur, virtuel pour assurer une séquence de destruction propre.
 *
 * Le destructeur ne fait rien de spécial.
 */
Cylindre::~Cylindre()
{}

/** Permet d'accéder à l'axe du cylindre.
 *
 * Fait appel à BaseCylindre::axe().
 *
 * @return une référence constante sur BaseCylindre::Axe.
 */
const VecteurU& Cylindre::axe() const
{
    return BCylindre -> axe();
}

/** Permet d'accéder au point d'origine du cylindre.
 *
 * Fait appel à BaseCylindre::point().
 *
 * @return une référence constante sur BaseCylindre::Point.
 */
const Coord& Cylindre::point() const
{
    return BCylindre -> sommet();
}

/** Permet d'accéder au rayon du cylindre.
 *
 * Fait appel à BaseCylindre::rayon().
 *
 * @return une référence constante sur BaseCylindre::Rayon.
 */
const double& Cylindre::rayon() const
{
    return BCylindre -> rayonCylindre();
}

/** Permet d'accéder à la hauteur du cylindre.
 *
 * @return une référence constante sur Hauteur.
 */
const double& Cylindre::hauteur() const
{
    return Hauteur;
}
